#include "singleMember.h"
#include "asgkaCreater.h"
#include "asgka_common.h"
#include "asgkaCreateAgreementThread.h"
#include "global.h"
#include "common.h"
#include <map>
#include <string>
#include <windows.h>
#include <process.h>

#include <iostream>
using namespace std;

asgkaCreateAgreementThread::asgkaCreateAgreementThread()
:m_group(NULL)
{}

asgkaCreateAgreementThread::asgkaCreateAgreementThread(singleGroup *group)
:m_group(group)
{}

void asgkaCreateAgreementThread::init(singleGroup *group)
{
	m_group = group;
}

UINT asgkaCreateAgreementThread::threadWork()
{
	if (m_group == NULL)
		return -1;
	
	std::string strlogbegin("Key agreement for group (CREATE) ");
	strlogbegin.append(m_group->getGroupName());
	strlogbegin.append(" begin!\r\n");
	newLog(strlogbegin);
	cout << "Agreement begin!" << endl;
	cout << "===================================================" << endl;
	asgkaCreater *agree = new asgkaCreater(m_group);

	agree->generateMyOwnKeys();

	cout << "Public my Hs !" << endl;
	agree->publicMyPubH();

	std::string strwfh("Wait for the Hs of the group named ");
	strwfh.append(m_group->getGroupName());
	strwfh.append(" (CREATE) \r\n");
	newLog(strwfh);
	cout << "Wait for the Hs " << endl;
	// Wait for the Hs
	while (!m_group->isAllHOK())
	{
		Sleep(10);
	}

	std::string strhok("Hs for key agreement of the group named ");
	strhok.append(m_group->getGroupName());
	strhok.append(" (CREATE)  OK\r\n");
	newLog(strhok);
	// Now this client has gotten all of the needed public key h
	cout << "Compute my public keys" << endl;

	agree->computeMyPubKeysGroupO();
	cout << "public my public keys " << endl;
	agree->publicMyPubKeysGroup();

	// I'm the leader
	if ( (localname.compare(m_group->getGroupLeader()->getMemberName())) == 0 )
	{
		// Wait for the As and Rs
		std::string strwfra("Wait for the Rs and As of the group named ");
		strwfra.append(m_group->getGroupName());
		strwfra.append(" (CREATE) \r\n");
		newLog(strwfra);
		while (!m_group->isAllAOK() || !m_group->isAllROK())
		{
			Sleep(10);
		}
		std::string strraok("Rs and As for key agreement of the group named ");
		strraok.append(m_group->getGroupName());
		strraok.append(" (CREATE)  OK\r\n");
		newLog(strraok);
		agree->generateAgreementKey();
		cout << "Public the ciphertexts" << endl;
		agree->publicCiphertexts();
	}
	else
	{
		std::string strwfo("Wait for the Os of the group named ");
		strwfo.append(m_group->getGroupName());
		strwfo.append(" (CREATE) \r\n");
		newLog(strwfo);
		cout << "Wait for the Os" << endl;
		// Wait for the Os
		while (!m_group->isAllXigamaOK())
		{
			Sleep(10);
		}

		std::string strcdk("Now computer the decrypt key of the group named ");
		strcdk.append(m_group->getGroupName());
		strcdk.append(" (CREATE) \r\n");
		newLog(strcdk);

		// Now we can calculate the decryption key
		cout << "Compute decrypt key" << endl;
		agree->computeMyDecryptKey();

		cout << "Wait for the ciphtexts" << endl;
		while (!m_group->isCipherTextOK())
		{
			Sleep(10);
		}

		agree->computeAgreedKey();
		std::string strkeycom("Agreed key of the group named ");
		strkeycom.append(m_group->getGroupName());
		strkeycom.append(" (CREATE) OK \r\n");
		newLog(strkeycom);
	}

	agree->updateElementsofGroup();

	c_asgka_element agreedkey = agree->getAgreedKey();
	for (int i = 0; i < LENGTH; i++)
		cout << agreedkey[i];
	cout << endl;



	delete agree;
	return 0;
}
